// package com.gitee.c0dehvb.reactivesamples.reactivesamples.config;
//
// import com.gitee.c0dehvb.reactive.sample.r2dbc.metadata.MySQLR2dbcSchemaMetaDataLoader;
// import com.gitee.c0dehvb.reactive.sample.r2dbc.SpringBootShardingRuleConfigurationProperties;
// import com.google.common.collect.Lists;
// import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
// import org.apache.shardingsphere.core.rule.ShardingRule;
// import org.apache.shardingsphere.core.yaml.swapper.ShardingRuleConfigurationYamlSwapper;
// import org.apache.shardingsphere.sharding.rewrite.context.ShardingSQLRewriteContextDecorator;
// import org.apache.shardingsphere.sharding.route.engine.ShardingRouteDecorator;
// import org.apache.shardingsphere.sql.parser.SQLParserEngine;
// import org.apache.shardingsphere.sql.parser.binder.metadata.schema.SchemaMetaData;
// import org.apache.shardingsphere.underlying.common.config.DatabaseAccessConfiguration;
// import org.apache.shardingsphere.underlying.common.config.properties.ConfigurationProperties;
// import org.apache.shardingsphere.underlying.common.database.type.dialect.MySQLDatabaseType;
// import org.apache.shardingsphere.underlying.common.metadata.ShardingSphereMetaData;
// import org.apache.shardingsphere.underlying.common.metadata.datasource.DataSourceMetas;
// import org.apache.shardingsphere.underlying.rewrite.SQLRewriteEntry;
// import org.apache.shardingsphere.underlying.route.DataNodeRouter;
// import org.springframework.beans.BeansException;
// import org.springframework.beans.factory.config.BeanPostProcessor;
// import org.springframework.boot.autoconfigure.r2dbc.R2dbcProperties;
// import org.springframework.boot.context.properties.EnableConfigurationProperties;
// import org.springframework.r2dbc.core.DatabaseClient;
// import org.springframework.stereotype.Component;
// import org.springframework.util.StringUtils;
//
// import javax.annotation.Resource;
// import java.util.HashMap;
// import java.util.Map;
// import java.util.Properties;
// import java.util.regex.Matcher;
// import java.util.regex.Pattern;
//
// /**
//  * @author LiYilin
//  * @since 2022/5/28 11:47 AM
//  **/
// @Component
// public class DatabaseClientBeanPostProcessor implements BeanPostProcessor {
//     private static final String databaseType = "MySQL";
//     private static final String DEFAULT_DATA_NODE = "db";
//     private static final String ACTUAL_DATA_NODE_SPLITTER = ".";
//     private static final Pattern WITH_SCHEMA_PATTERN = Pattern.compile("^\\w+\\.");
//
//     @Resource
//     private SpringBootShardingRuleConfigurationProperties shardingRule;
//     @Resource
//     private Properties properties;
//     @Resource
//     private R2dbcProperties r2dbcProperties;
//
//     @Override
//     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//         if (bean instanceof DatabaseClient && !(bean instanceof TableShardingDatabaseClient)) {
//             DatabaseClient rawDatabaseClient = (DatabaseClient) bean;
//             ConfigurationProperties configurationProperties = new ConfigurationProperties(properties);
//             shardingRule.getTables().forEach((table, yamlTableRuleConfiguration) -> {
//                 String actualDataNodes = yamlTableRuleConfiguration.getActualDataNodes();
//                 if (StringUtils.hasText(actualDataNodes)) {
//                     Matcher matcher = WITH_SCHEMA_PATTERN.matcher(actualDataNodes);
//                     if (!matcher.find()) {
//                         yamlTableRuleConfiguration.setActualDataNodes(DEFAULT_DATA_NODE + ACTUAL_DATA_NODE_SPLITTER + actualDataNodes);
//                     } else {
//                         yamlTableRuleConfiguration.setActualDataNodes(matcher.replaceFirst(DEFAULT_DATA_NODE + ACTUAL_DATA_NODE_SPLITTER));
//                     }
//                 }
//             });
//             ShardingRuleConfiguration configuration = new ShardingRuleConfigurationYamlSwapper().swap(shardingRule);
//             ShardingRule rule = new ShardingRule(configuration, Lists.newArrayList(DEFAULT_DATA_NODE));
//             MySQLR2dbcSchemaMetaDataLoader loader = new MySQLR2dbcSchemaMetaDataLoader();
//             SchemaMetaData schemaMetaData = loader.load(rule, 4, rawDatabaseClient);
//             SQLParserEngine parserEngine = new SQLParserEngine(databaseType);
//             ShardingSphereMetaData shardingSphereMetaData =
//                     new ShardingSphereMetaData(createDataSourceMetas(r2dbcProperties), schemaMetaData);
//             DataNodeRouter dataNodeRouter = new DataNodeRouter(shardingSphereMetaData, configurationProperties,
//                                                                parserEngine);
//             dataNodeRouter.registerDecorator(rule, new ShardingRouteDecorator());
//             SQLRewriteEntry sqlRewriteEntry = new SQLRewriteEntry(schemaMetaData, configurationProperties);
//             ShardingSQLRewriteContextDecorator sqlRewriteContextDecorator =
//                     new ShardingSQLRewriteContextDecorator();
//             sqlRewriteEntry.registerDecorator(rule, sqlRewriteContextDecorator);
//             return new TableShardingDatabaseClient(rawDatabaseClient, DEFAULT_DATA_NODE, schemaMetaData, parserEngine,
//                                                    dataNodeRouter, sqlRewriteEntry);
//         }
//         return bean;
//     }
//
//     private DataSourceMetas createDataSourceMetas(R2dbcProperties r2dbcProperties) {
//         Map<String, DatabaseAccessConfiguration> databaseAccessConfigurationMap = new HashMap<>();
//         String url = r2dbcProperties.getUrl().replace("r2dbcs", "jdbc")
//                 .replace("r2dbc", "jdbc");
//         DatabaseAccessConfiguration databaseAccessConfiguration =
//                 new DatabaseAccessConfiguration(url, r2dbcProperties.getUsername(),
//                                                 r2dbcProperties.getPassword());
//         databaseAccessConfigurationMap.put(DEFAULT_DATA_NODE, databaseAccessConfiguration);
//         return new DataSourceMetas(new MySQLDatabaseType(), databaseAccessConfigurationMap);
//     }
// }
